home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / scope / 001-025 / scopedisk14 / hamklido / hamkaleid.c next >
C/C++ Source or Header  |  1995-03-18  |  9KB  |  297 lines

  1. /*                        ______________________
  2.                          /
  3.                         /   Kaleidoscope           ____________________
  4.  ______________________/            by            /
  5.                                    Greg Searle   /
  6.                           ______________________/
  7.  
  8.    Creates a pretty, moving pattern on a lowres HAM screen.  Colors change
  9. smoothly as the pattern is drawn, randomly moving through all 4096 colors.
  10. This program uses the famous "bouncing ball" to guide the pattern.  A moving
  11. point follows a straight line until it hits the edge of the screen, where it
  12. "bounces off" somewhat randomly.
  13.  
  14.    This program multitasks fine.  The program is active only once per screen
  15. refresh (60 times per second), leaving plenty of time for other programs.  The
  16. regular screen gadgets (dragbar, close box, layering gadgets) are hidden under
  17. the pattern.  Just hit the close box at the upper-right to shut down the
  18. program.
  19.  
  20. */
  21. #include <exec/types.h>
  22. #include <graphics/gfxbase.h>
  23. #include <graphics/gfxmacros.h>
  24. #include <intuition/intuition.h>
  25.  
  26. struct GfxBase        *GfxBase;
  27. struct IntuitionBase  *IntuitionBase;
  28. struct BitMap         *bmap;
  29. struct RastPort       *rp;
  30. struct ViewPort       *vp;
  31. struct Screen         *scr;
  32. struct Window         *win;
  33.  
  34. struct NewScreen screen = {
  35.    0, 0, 0, 0, 0,              /* LeftEdge, TopEdge, Width, Height, Depth */
  36.    -1, -1,                    /* DetailPen, BlockPen (default)           */
  37.    0, CUSTOMSCREEN,          /* ViewModes, Type                         */
  38.    NULL, NULL,              /* *Font (default), *DefaultTitle          */
  39.    NULL, NULL              /* *Gadgets, *CustomBitMap                 */
  40. };
  41.  
  42. #define WFLAGS  WINDOWCLOSE | SIMPLE_REFRESH | ACTIVATE | \
  43.                 BORDERLESS | BACKDROP | RMBTRAP
  44. #define WIDCMP  CLOSEWINDOW
  45.  
  46. struct NewWindow window = {   /* This will only create a close box        */
  47.    0, 0, 13, 10,             /* LeftEdge, TopEdge, Width, Height         */
  48.    -1, -1,                  /* DetailPen, BlockPen (default)            */
  49.    WIDCMP,                 /* IDCMPFlags                               */
  50.    WFLAGS,                /* Flags                                    */
  51.    NULL, NULL,           /* *FirstGadget, *CheckMark                 */
  52.    NULL, NULL, NULL,    /* *Title, *Screen (to be set), *BitMap     */
  53.    0, 0, 0, 0,         /* MinWidth, MinHeight, MaxWidth, MaxHeight */
  54.    CUSTOMSCREEN       /* Type                                     */
  55. };
  56.  
  57. #define WIDTH     320
  58. #define HEIGHT    200
  59. #define DEPTH     6
  60. #define LENGTH    60
  61. #define LINES     3
  62.  
  63. short fromCLI = 0;
  64.  
  65. main (argv, argc)
  66.   char *argv[];
  67.   long argc;
  68. {
  69.    short          error;
  70.    long           x[LINES], dx[LINES], xx, yy, i, j, k, l, cc = 0;
  71.    float          y[LINES], dy[LINES], p[3][LINES], dp[3][LINES];
  72.  
  73.    struct IntuiMessage *message, *GetMsg();
  74.  
  75.    fromCLI = argc;
  76.    if (error = OpenLibraries()) GoAway(error);
  77.    if (error = CreateScreen("Screen", WIDTH, HEIGHT, DEPTH, (short)HAM))
  78.        GoAway(error);
  79.    ShowTitle(scr, FALSE);
  80.    SetRGB4 (vp, 0L, 0L, 0L, 0L);
  81.    SetRast (rp, 0L);
  82.    SetDrMd (rp, JAM1);
  83.  
  84.    rnd ((short) -VBeamPos());    /*  Init random number generator */
  85.    for (l = 0; l < LINES; l++) {
  86.       x[l]  = rnd (WIDTH);
  87.       y[l]  = rnd (HEIGHT);
  88.       dx[l] = rnd(1) * 2 - 1;        /* x changes only by one, */
  89.       do                            /* keeping pattern smooth */
  90.          dy[l] = (float)(rnd(23) - 11) / 6;
  91.       while (dy[l] == 0);
  92.                                   /* Init colors                          */
  93.       for (i = 0; i < 3; i++) {  /* Uses "bouncing ball" technique to    */
  94.          p[i][l] = rnd(15);     /* change colors smoothly, yet randomly */
  95.          do
  96.             dp[i][l] = (float)(rnd(21) - 10) / 3;
  97.          while (dp[i][l] == 0.0);
  98.       }
  99.    }
  100.  
  101.    /********** MAIN LOOP **********/
  102.  
  103.    while (!GetMsg(win -> UserPort)) {
  104.  
  105.       /* Set current color, then increment colors for each line.        */
  106.      /*  R, G, and B are controlled by "bouncing" vectors.             */
  107.     /*   Once they reach their limit, they reverse at a random speed. */
  108.  
  109.       WaitTOF();      /* Delay - save multitasking */
  110.  
  111.       if (++cc > 2) cc = 0;
  112.       for (l = 0; l < LINES; l++) {
  113.  
  114.          SetAPen (rp, cc * 16L + 16L + (long) p[cc][l]);
  115.          if (!cc) {
  116.             for (i = 0; i < 3; i++) {
  117.                if ((p[i][l] += dp[i][l]) > 15  ||  p[i][l] < 0) {
  118.                   if (p[i][l] > 15.0)
  119.                      p[i][l] = 30.0 - p[i][l];
  120.                   else
  121.                      p[i][l] = -p[i][l];
  122.                   do
  123.                      dp[i][l] = ((p[i][l] < 8) ? 1 : -1) * (float)(rnd(10) + 1) / 3;
  124.                   while (dp[i][l] == 0.0);
  125.                }
  126.             }
  127.          }
  128.  
  129.        /* Draw:  first x,y & mirrors, then y,x & mirrors.                 */
  130.       /*  i & j are y and x converted into x and y, respectively.        */
  131.      /*   This allows use of the full screen, instead of just a square. */
  132.    
  133.          i = (long)(y[l] / (float)HEIGHT * (float)WIDTH);
  134.          j = (long)((float)x[l] / (float)WIDTH  * (float)HEIGHT);
  135.          xx =  WIDTH - x[l];
  136.          yy = HEIGHT - (long)y[l];
  137.          Line (rp,  x[l],  (long)y[l]-LENGTH/2,  x[l],  (long)y[l]+LENGTH/2);
  138.          Line (rp, xx,  (long)y[l]-LENGTH/2, xx,  (long)y[l]+LENGTH/2);
  139.          Line (rp,  x[l], yy-LENGTH/2,  x[l], yy+LENGTH/2);
  140.          Line (rp, xx, yy-LENGTH/2, xx, yy+LENGTH/2);
  141.    
  142.          xx =  WIDTH - i;
  143.          yy = HEIGHT - j;
  144.          for (k = 0; k < 3; k++) {
  145.             SetDrPt (rp, 0x92492492 >> k);
  146.             SetAPen (rp, k * 16L + 16L + (long) p[k][l]);
  147.             Line (rp,  i-LENGTH/2,  j,  i+LENGTH/2,  j);
  148.             Line (rp, xx-LENGTH/2,  j, xx+LENGTH/2,  j);
  149.             Line (rp,  i-LENGTH/2, yy,  i+LENGTH/2, yy);
  150.             Line (rp, xx-LENGTH/2, yy, xx+LENGTH/2, yy);
  151.          }
  152.          SetDrPt (rp, 0xFFFFFFFF);
  153.  
  154.          /* Increment x,y.  Check if bounced off edge. */
  155.  
  156.          if ((x[l] += dx[l]) < 0  ||  x[l] > WIDTH) {
  157.             x[l] -= dx[l];
  158.             dx[l] = -dx[l];
  159.          }
  160.          if ((y[l] += dy[l]) < 0  ||  y[l] > (float)HEIGHT) {
  161.             y[l] -= dy[l];
  162.             dy[l] = -dy[l];
  163.             do
  164.                dy[l] = ((dy[l]<0) ? -1:1) * (float)(rnd(23) - 11) / 6;
  165.             while (dy[l] == 0);
  166.          }
  167.       }  /* for l */
  168.  
  169.    }  /* while */
  170.  
  171.    GoAway(0);
  172. }  /* main */
  173.  
  174. Line (rp, x1, y1, x2, y2)   /* Just draws a line and checks for edges */
  175.   struct RastPort *rp;
  176.   long x1, y1, x2, y2;
  177. {
  178.  
  179.    if (x1 < 0) x1 = 0;
  180.       else if (x1 > WIDTH-1) x1 = WIDTH-1;
  181.    if (y1 < 0) y1 = 0;
  182.       else if (y1 > HEIGHT-1) y1 = HEIGHT-1;
  183.  
  184.    if (x2 < 0) x2 = 0;
  185.       else if (x2 > WIDTH-1) x2 = WIDTH-1;
  186.    if (y2 < 0) y2 = 0;
  187.       else if (y2 > HEIGHT-1) y2 = HEIGHT-1;
  188.  
  189.    Move (rp, x1, y1);
  190.    Draw (rp, x2, y2);
  191. }
  192.  
  193. short OpenLibraries()
  194. {
  195.    void *OpenLibrary();
  196.  
  197.    if (!(IntuitionBase = (struct IntuitionBase *)
  198.       OpenLibrary ("intuition.library", 1L))) return 1;
  199.  
  200.    if (!(GfxBase = (struct GfxBase *)
  201.       OpenLibrary ("graphics.library", 1L))) return 2;
  202.  
  203.    return 0;
  204. }  /* OpenLibraries */
  205.  
  206. short CreateScreen (title, width, height, depth, modes)
  207.   char title[];
  208.   short width, height, depth, modes;
  209. {
  210.    struct Screen *OpenScreen();
  211.    struct Window *OpenWindow();
  212.  
  213.    screen.Width      = width;
  214.    screen.Height     = height;
  215.    screen.Depth      = depth;
  216.    screen.ViewModes  = modes | ((width  > 320) ? HIRES:0)
  217.                              | ((height > 200) ?  LACE:0);
  218.  
  219.    if (!(scr = OpenScreen (&screen))) return 3;
  220.    window.Screen = scr;
  221.    if (!(win = OpenWindow (&window))) return 4;
  222.  
  223.    vp = &(scr -> ViewPort);
  224.    rp = &(scr -> RastPort);
  225.    return 0;
  226. }  /* CreateScreen */
  227.  
  228. GoAway(error)
  229.   short error;
  230. {
  231.    Report (error);
  232.    if (IntuitionBase) CloseLibrary (IntuitionBase);
  233.    if (GfxBase)       CloseLibrary (GfxBase);
  234.    if (win)           CloseWindow (win);
  235.    if (scr)           CloseScreen (scr);
  236.    exit (0L);
  237. }  /* GoAway */
  238.  
  239. Report (error)
  240.   short error;
  241. {
  242.    if (!error) return;
  243.    if (!fromCLI)
  244.       DisplayBeep(NULL);
  245.    else
  246.       switch (error) {
  247.          case 1:  printf("Can't open Intuition.\n");  break;
  248.          case 2:  printf("Can't open Graphics.\n");   break;
  249.          case 3:  printf("Can't open Screen.\n");     break;
  250.          case 4:  printf("Can't open Window.\n");     break;
  251.          default: printf("Undefined error.\n");       break;
  252.       }  /* switch */
  253. }  /* Report */
  254.  
  255. #asm
  256.  
  257. *\
  258. *  :ts=8
  259. * Yet Another random number generator.  By Leo Schwab.
  260. * Based on an idea posted on the USENET (Thanks, Sam Dicker!)
  261. * For the Manx assembler.
  262. *
  263. * Calling convention:
  264. *  short rnd (range);
  265. *  short range;
  266. *
  267. * 8606.30
  268. */
  269.  
  270.       public    _rnd
  271.  
  272. _rnd      lea   rndseed,a0   ;Get address of seed
  273.       move.w   4(sp),d1   ;Get range argument
  274.       tst.w   d1
  275.       ble.s   setseed      ;Go reset seed
  276.  
  277.  
  278.       move.l   (a0),d0      ;Get seed
  279.       ADD.L   D0,D0
  280.       BHI.S   over
  281.       EORI.L  #$1D872B41,D0
  282. over
  283.       move.l   d0,(a0)      ;Save new seed
  284.       andi.l   #$ffff,d0   ;Coerce into word
  285.       divu   d1,d0      ;Divide by range
  286.       swap   d0      ; and get remainder (modulus)
  287.       rts
  288.  
  289. setseed      neg.w   d1      ;Probably don't need this
  290.       move.l   d1,(a0)
  291.       rts
  292.  
  293.       dseg
  294. rndseed      dc.l   0
  295.       cseg
  296. #endasm
  297.